const mongoose = require('mongoose');
const async = require('async');
const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;

const Business = new Schema({
    name: String,
    logo: String,
    description: String,
    website: String,
    created_date: { type: Date, default: Date.now }
});

exports.Business = Business;

const User = new Schema({
    name: String,
    email: String,
    password: String,
    profile_image: { type: String, default: 'dashboard/images/default_profile_image.png' },
    hash_id: { type: String },
    industry: String,
    locale: { type: String, default: 'zh-CN' },
    type: { type: String, default: 'register' }, //possible value: register, trial, woadm(WeChat Official Account Direct Message)
    ref: { type: String, default: 'direct' },
    third_party_id: { type: String, default: null }, //TODO: store the user id of third party platform, like BlueMP, Weibo, QQ, etc.
    qr_code: { type: String, default: null },
    created_date: { type: Date, default: Date.now }
});

User.statics.findUserByEmail = function (email, cb) {
    return this.find({ email: email }, cb);
};

User.statics.findUserByThirdPartyInfo = function (thirdPartyId, ref, cb) {
    return this.find({ third_party_id: thirdPartyId, ref: ref }, cb);
};

User.statics.findUserById = function (id, cb) {
    //return this.find({_id: id}, cb);
    this.findById(id, cb)
};
User.statics.findUserByIdentifier = function (identifier, cb) {
    return this.find({ hash_id: identifier }, cb);
};
User.statics.getUsers = function (cb) {
    return this.find(cb);
};
User.statics.removeUserByUserId = function (user_id, cb) {
    return this.remove({ _id: user_id }, cb);
};

User.statics.findUsersByThirdPartyId = function (thirdPartyId, ref, cb) {
    return this.find({ third_party_id: thirdPartyId, ref: ref }, cb);
};

exports.User = User;

var UserPreference = new Schema({
    user_id: String,
    preference: String,
    last_updated_date: { type: Date, default: Date.now },
    created_date: { type: Date, default: Date.now }
});

var Wall = new Schema({
    user_id: String,
    app_id: String, //TODO: Need to remove
    name: String,
    logo: String,
    background: { type: String, default: '//cdn2.parllay.cn/images/default_wall_background.png' },
    qr_code: String,
    description: String,
    administrators: Array,
    author: Array,
    operations: Array,
    settings: { type: Schema.Types.Mixed, default: {} },
    sources: { type: Array, default: [] },
    mode: { type: Number, default: 1 },
    template: { type: String, default: 'timeline' },
    user_authority: { type: Number, default: 1 },
    tag_authority: { type: String },
    background_color: { type: String },
    created_date: { type: Date, default: Date.now },
    last_updated_date: { type: Date, default: Date.now }
});

Wall.statics.findWallsByUserId = function (userId, cb) {
    return this.find({ user_id: userId }, cb);
};

Wall.statics.findWallsByAppId = function (userId, appId, cb) {
    return this.find({ user_id: userId, app_id: appId }, cb);
};

Wall.statics.findWallById = function (wallId, cb) {
    this.findById(wallId, cb);
};

Wall.statics.removeWallByWallId = function (wall_id, cb) {
    return this.remove({ _id: wall_id }, cb);
};

exports.Wall = Wall;

var WallRealTimeConfig = new Schema({
    order_id: Number,
    wall_id: String,
    start_date: Date,
    end_date: Date,
    is_active: { type: Boolean, default: true },
    created_date: { type: Date, default: Date.now }
});

WallRealTimeConfig.statics.getRealTimeConfigByWallId = function (wallId, all, callback) {
    var now = new Date();
    if (all) {
        this.find({ is_active: true, wall_id: wallId, end_date: { $gte: now } }, callback).sort({ end_date: 1 });
    } else {
        this.find({ is_active: true, wall_id: wallId, start_date: { $lte: now }, end_date: { $gt: now } }, callback);
    }
};

exports.WallRealTimeConfig = WallRealTimeConfig;

var WallUser = new Schema({
    wall_id: String,
    open_id: String,
    union_id: String,
    name: String,
    gender: String,
    province: String,
    city: String,
    country: String,
    profile_image: { type: String, default: '/dashboard/images/default_profile_image.png' },
    refresh_token: String,
    privilege: String,
    is_anonymous: { type: Boolean, default: false },
    source: { type: String, default: 'wechat' }, // wechat, weibo, anonymous(phone, computer(mac, windows, linux))
    created_date: { type: Date, default: Date.now }
});

WallUser.statics.getUserByOpenId = function (openId, wallId, cb) {
    this.find({ open_id: openId, wall_id: wallId }, cb);
};

WallUser.statics.findWallUserById = function (id, cb) {
    this.findById(id, cb);
};

WallUser.statics.findWallUsersByThirdPartyId = function (thirdPartyId, type, wallId, cb) {
    this.find({ open_id: thirdPartyId, source: type, wall_id: wallId }, cb);
};

WallUser.statics.findUsersByWallId = function (wallId, params, cb) {
    var conditions = {
        wall_id: wallId
    };
    if (params.since !== 'now') {
        if (params.type === 'new') {
            if (params.order === 'asc') {
                conditions.created_date = {
                    $lt: params.since
                };
            } else {
                conditions.created_date = {
                    $gt: params.since
                };
            }
        }

        if (params.type === 'old') {
            if (params.order === 'asc') {
                conditions.created_date = {
                    $gt: params.since
                };
            } else {
                conditions.created_date = {
                    $lt: params.since
                }
            }
        }
    }

    if (params.ids && params.ids.length > 0) {
        conditions._id = {
            $in: params.ids
        };
    }

    if (params.source) {
        conditions.source = params.source;
    }
    var order = -1;
    if (params.order && ['desc', 'asc'].indexOf(params.order) >= 0) {
        switch (params.order) {
            case 'asc':
                order = 1;
                break;
            default:
                order = -1;
        }
    }

    if (params.searchWord) {
        conditions.name = new RegExp(params.searchWord, "i");
    }

    return this.find(conditions).sort({ created_date: order }).limit(Number(params.count)).exec(cb);
};

WallUser.statics.getUserCountByWallId = function (wallId, cb) {
    this.count({ wall_id: wallId }, cb);
};

exports.WallUser = WallUser;

var WallPhoto = new Schema({
    wall_id: String,
    creator_id: String,
    photo_url: String,
    description: String,
    ratio: Number,
    asset_type: { type: String, default: 'photo' },
    asset_meta_data: { type: Schema.Types.Mixed, default: {} },
    likes: { type: Array, default: [] },
    operations: { type: Array, default: [] },
    additional_url: String,
    statistics: { type: Schema.Types.Mixed, default: {} },
    source: { type: String, default: 'wechat' }, // wechat, PC, dianping, weibo
    status: { type: String, default: 'pending' }, // pending, approved, rejected and deleted
    last_updated_date: { type: Date, default: Date.now },
    created_date: { type: Date, default: Date.now },
    created_timestamp: { type: Number, default: Date.now() }
});

WallPhoto.statics.findPhotosByWallId = function (wallId, params, cb) {
    params.wall_id = wallId;
    this.findPhotosByCriteria(params, cb);
};

WallPhoto.statics.findPhotosByCriteria = function (params, cb) {
    cb = (typeof cb === 'function') ? cb : function () { };

    var conditions = {};

    if (params.wall_id) {
        conditions.wall_id = params.wall_id;
    }

    if (params.user_id) {
        params.creator_id = params.user_id;
    }

    if (params.mode === 'latest') {
        if (params.status) {
            conditions.status = params.status;
        }
        if (params.tagId) {
            conditions.id = params.asset_id;
        }
        if (params.since !== 'now') {
            if (params.type === 'new') {
                conditions.last_updated_date = {
                    $gt: params.since
                };
            }
            if (params.type === 'old') {
                conditions.last_updated_date = {
                    $lt: params.since
                }
            }
        }
    }

    if (params.source) {
        conditions.source = params.source;
    }

    //TODO: implement filtering assets by asset ids
    if (params.assetIds && params.assetIds.length > 0) {
        conditions._id = {
            '$in': params.assetIds
        }
    }

    switch (params.mode) {
        case 'latest':
            return this.find(conditions).sort({ last_updated_date: -1 }).limit(Number(params.count)).exec(cb);
        case 'hot':
            conditions.status = 'approved';
            var projects = {};
            WallPhoto.eachPath(function (path) {
                projects[path] = 1;
            });
            projects.likesLen = { "$size": "$likes" };
            return this.aggregate().match(conditions).project(projects).sort({ likesLen: -1 }).limit(Number(params.count)).exec(cb);
        default:
            return cb([]);
    }

};

WallPhoto.statics.findLinkStatisticsByWallId = function (wallId, params, cb) {
    cb = (typeof cb === 'function') ? cb : function () { };

    var conditions = {};

    if (params.wall_id) {
        conditions.wall_id = params.wall_id;
    }

    if (params.user_id) {
        params.creator_id = params.user_id;
    }


    if (params.status) {
        conditions.status = params.status;
    }
    if (params.tagId) {
        conditions.id = params.asset_id;
    }
    if (params.since !== 'now') {
        if (params.type === 'new') {
            conditions.created_date = {
                $gt: params.since
            };
        }
        if (params.type === 'old') {
            conditions.created_date = {
                $lt: params.since
            }
        }
    }

    if (params.source) {
        conditions.source = params.source;
    }

    //TODO: implement filtering assets by asset ids
    if (params.assetIds && params.assetIds.length > 0) {
        conditions._id = {
            '$in': params.assetIds
        }
    }

    conditions.additional_url = { $exists: true };


    return this.find(conditions).sort({ last_updated_date: -1 }).limit(Number(params.count)).exec(cb);
};

WallPhoto.statics.findPhotoById = function (photoId, cb) {
    this.findById(photoId, cb);
};

WallPhoto.statics.getPhotoCountByWallId = function (wallId, cb) {
    this.count({ wall_id: wallId }, cb);
};

WallPhoto.statics.findPhotoByCreatorId = function (creator_id, cb) {
    this.find({ creator_id: creator_id }, cb);
};
WallPhoto.statics.removeAssetsByWallId = function (wall_id, cb) {
    return this.remove({ wall_id: wall_id }, cb);
};

WallPhoto.statics.findPhotosByUserId = function (userId, params, cb) {
    params.user_id = userId;
    this.findPhotosByCriteria(params, cb);
};

exports.WallPhoto = WallPhoto;

var LatestUploadWallPhotos = new Schema({
    wall_id: String,
    creator_id: String,
    user_id: String,
    photo_url: String,
    description: String,
    ratio: Number,
    asset_type: { type: String, default: 'photo' },
    asset_meta_data: { type: Schema.Types.Mixed, default: {} },
    likes: { type: Array, default: [] },
    operations: { type: Array, default: [] },
    additional_url: String,
    statistics: { type: Schema.Types.Mixed, default: {} },
    source: { type: String, default: 'wechat' }, // wechat, PC, dianping, weibo
    status: { type: String, default: 'pending' }, // pending, approved, rejected and deleted
    last_updated_date: { type: Date, default: Date.now },
    created_date: { type: Date, default: Date.now },
    created_timestamp: { type: Number, default: Date.now() }
});

LatestUploadWallPhotos.statics.findLatestPhotosByWallId = function (params, cb) {
    var param = { wall_id: params.wall_id };
    param.created_timestamp = {
        $gt: params.since
    };
    param.user_id = params.userId;

    this.find(param, cb);
}

LatestUploadWallPhotos.statics.findNotWallIdUpload = function (params, cb) {
    var param = {};
    param = {
        $and: [
            {
                created_timestamp: {
                    $gt: params.since
                }
            },
            {
                wall_id: {
                    $not: {
                        $eq: params.wall_id
                    }
                }
            },
            {
                user_id: params.userId
            }
        ]
    }
    this.find(param, cb);
}

LatestUploadWallPhotos.statics.getLatestUploadTime = function (params, cb) {
    return this.find({ user_id: params.userId }).sort({ created_date: -1 }).exec(cb);
}

LatestUploadWallPhotos.statics.findPhotoById = function (photoId, cb) {
    this.findById(photoId, cb);
};

LatestUploadWallPhotos.statics.removePhoto = function (photoId, cb) {
    this.remove({ _id: photoId }, cb);
}

exports.LatestUploadWallPhotos = LatestUploadWallPhotos;

var ManagedOfficialAccount = new Schema({
    user_id: String,
    app_id: String,
    name: String,
    logo: { type: String, default: '/dashboard/images/wechat/logo-32x32.png' },
    refresh_token: String,
    access_token: String,
    qr_code: { type: String, default: null },
    service_type: { type: Number, default: -1 },
    verify_type: { type: Number, default: -2 },
    metadata: { type: Schema.Types.Mixed, default: {} },
    type: { type: String, default: 'oauth' },
    social_type: { type: String, default: 'wechat' }, //wechat, weibo, dianping
    status: { type: String, default: 'normal' },
    last_updated_date: { type: Date, default: Date.now },
    created_date: { type: Date, default: Date.now }
});

ManagedOfficialAccount.statics.findAccountsByUserId = function (userId, cb) {
    return this.find({ user_id: userId }, cb);
};

ManagedOfficialAccount.statics.findAccountByAppId = function (userId, appId, cb) {
    return this.find({ user_id: userId, app_id: appId }, cb);
};

ManagedOfficialAccount.statics.findAccountByAppId1 = function (appId, socialType, cb) {
    return this.find({ app_id: appId, social_type: socialType }, cb);
};

ManagedOfficialAccount.statics.findAllAccounts = function (cb) {
    return this.find(cb);
};

ManagedOfficialAccount.statics.findAccountsByCriteria = function (criteria, cb) {
    return this.find(criteria, cb);
};

exports.ManagedOfficialAccount = ManagedOfficialAccount;


var Comment = new Schema({
    photo_id: String,
    content: String,
    user: {
        id: String,
        name: {
            type: String,
            default: '匿名用户'
        },
        profile_image: {
            type: String,
            default: 'dashboard/images/default_profile_image.png'
        }
    },
    created_date: { type: Date, default: Date.now }
});

Comment.statics.findCommentsByPhotoId = function (photo_id, params, cb) {
    var conditions = {
        photo_id: photo_id
    };
    if (params.since !== 'now') {
        if (params.type === 'new') {
            conditions.created_date = {
                $gt: params.since
            };
        }

        if (params.type === 'old') {
            conditions.created_date = {
                $lt: params.since
            }
        }
    }
    return this.find(conditions).sort({ created_date: -1 }).limit(Number(params.count)).exec(cb);
};

Comment.statics.findCommentCountByPhotoId = function (photo_id, cb) {
    return this.count({ photo_id: photo_id }, cb);
};

exports.Comment = Comment;


var Sales = new Schema({
    name: String,
    email: String,
    telephone: Number,
    sales_id: String
});

Sales.statics.findRandomData = function (random, cb) {
    return this.find().skip(random).limit(1).exec(cb);
};

Sales.statics.getSalesCount = function (cb) {
    return this.count(cb);
};

Sales.statics.findSalesBySalesId = function (sales_id, cb) {
    return this.find({ sales_id: sales_id }, cb);
};

exports.Sales = Sales;

var DemoRequest = new Schema({
    name: String,
    email: String,
    company: String,
    telephone: String,
    industry: String,
    sales_id: String,
    status: {
        type: String,
        default: 'unsent'
    }
});

exports.DemoRequest = DemoRequest;

var Tag = new Schema({
    tag: String,
    user_id: String,
    wall_id: String,
    created_date: { type: Date, default: Date.now }
});

Tag.statics.findTagById = function (id, cb) {
    return this.findById(id, cb);
};

Tag.statics.findTagByUserId = function (user_id, cb) {
    var conditions = {
        user_id: user_id
    };
    return this.find(conditions).exec(cb);
};
Tag.statics.findTagByWallId = function (wall_id, cb) {
    var conditions = {
        wall_id: wall_id
    };
    return this.find(conditions).exec(cb);
};




exports.Tag = Tag;

var AssetTag = new Schema({
    asset_id: String,
    tag_id: String,
    created_date: { type: Date, default: Date.now }
});

AssetTag.statics.findByAssetId = function (asset_id, cb) {
    return this.find({ asset_id: asset_id }, cb);
};

AssetTag.statics.findTagByTagId = function (tag_id, cb) {
    return this.find({ tag_id: tag_id }, cb);
};

exports.AssetTag = AssetTag;





